package org.graduation.recruitment.filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.graduation.recruitment.utils.ResponseResult;
import org.graduation.recruitment.utils.Token;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * Token验证过滤器，用于拦截请求并进行Token验证。
 * 会首先检查请求路径是否在白名单内，若在则直接通过；
 * 若不在，会从请求中提取Token并进行验证。
 *
 * @WebFilter注解指定了过滤器的名称和要拦截的URL模式。
 */
@WebFilter(filterName = "TokenFilter", urlPatterns = "/*")
@Order(2)
@Slf4j
@Component
public class TokenFilter implements Filter {
    @Autowired
    private Token token;
    // 不检查token的白名单路径
    @Autowired
    private TokenFilterWhiteList whiteList;

    /**
     * 对请求进行过滤，如果路径在白名单内或请求是Swagger请求则直接通过，
     * 否则进行Token验证。
     *
     * @param servletRequest  请求对象
     * @param servletResponse 响应对象
     * @param filterChain     过滤器链，用于继续处理请求或中断处理
     * @throws IOException      如果发生输入/输出错误
     * @throws ServletException 如果发生servlet相关错误
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        log.debug("full path:{} [{}]", request.getRequestURL().toString(), request.getMethod());
        // 检查路径是否在白名单内或是否为Swagger请求
        if (whiteList.getWhiteList().contains(request.getServletPath()) || isSwagger(request)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            String tokenStr = token.getTokenByRequest(request);
            if (token.verifyToken(tokenStr)) {
                filterChain.doFilter(servletRequest, servletResponse);
            } else {
                log.info("token验证失败,token:" + tokenStr);
                // Token验证失败，返回错误信息
                ResponseResult<Void> result = ResponseResult.fail(-401, "token验证失败");
                String jsonResult = result.toJson();
                servletResponse.setContentType("application/json;charset=UTF-8");
                servletResponse.getWriter().write(jsonResult);
            }
        }
    }

    /**
     * 过滤器初始化方法，用于在应用启动时初始化过滤器。
     *
     * @param filterConfig 过滤器配置对象
     * @throws ServletException 如果初始化过程中发生servlet相关错误
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        log.info("初始化token白名单:" + whiteList.getWhiteList().toString());
    }

    /**
     * 过滤器销毁方法，用于在应用停止时释放过滤器资源。
     */
    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    /**
     * 判断请求是否为Swagger相关请求。
     *
     * @param request 请求对象
     * @return 如果请求是Swagger请求则返回true，否则返回false
     */
    private boolean isSwagger(HttpServletRequest request) {
        String path = request.getServletPath();
        return path.startsWith("/swagger-ui") || path.startsWith("/v3/");
    }

}
